//
//  YHClassObject.cpp
//  ThunderWarriors
//
//  Created by hlp on 12-12-28.
//
//

#include "YHClassFactory.h"
using namespace std;

#define DeclareBaseClass(__BaseClassName__) \
\
void* create##__BaseClassName__(void) { \
    void* pRet = new __BaseClassName__;\
    return pRet;\
}\
\
void deleteClass##__BaseClassName__(void* pInstance) {\
    delete (__BaseClassName__*)pInstance;\
}\
\
void setClass##__BaseClassName__(void* lhs, void* rhs){ \
    __BaseClassName__* pLhs = (__BaseClassName__*)lhs;\
    __BaseClassName__* pRhs = (__BaseClassName__*)rhs;\
    *pLhs = *pRhs;\
}

DeclareBaseClass(int)
DeclareBaseClass(string)
DeclareBaseClass(float)
DeclareBaseClass(double)
DeclareBaseClass(char)

/* //this is ok!
#define RegisterBaseClass(__BaseClassName__) \
{\
    YHClassObject baseClassObject;\
    baseClassObject.m_className = #__BaseClassName__;\
    YHClassFactory::sharedClassFactory()->registerClass(baseClassObject);\
}
*/
#define RegisterBaseClass(__BaseClassName__) \
    YHClassFactory::sharedClassFactory()->registerClass(#__BaseClassName__,\
                    class_selector(create##__BaseClassName__),\
                    delete_class_selector(deleteClass##__BaseClassName__), \
                    set_class_selector(setClass##__BaseClassName__));\

YHClassObject::YHClassObject(){
    
}

YHClassObject::YHClassObject(string className, CLASS_SELECTOR classSelector, DELETE_CLASS_SELECTOR deleteClassSelector, SET_CLASS_SELECTOR setClassSelector){
    m_className = className;
    m_classSelector = classSelector;
    m_deleteDlassSelector = deleteClassSelector;
    m_setClassSelector = setClassSelector;
    YHClassFactory::sharedClassFactory()->registerClass(*this);
}

YHClassFactory* YHClassFactory::m_shared_ClassFactory = NULL;
//map<string, YHClassObject> YHClassFactory::m_mapStringClassObjects = map<string, YHClassObject>();

YHClassFactory* YHClassFactory::sharedClassFactory(){
    if (NULL == m_shared_ClassFactory) {
        m_shared_ClassFactory = new YHClassFactory();
        if (!m_shared_ClassFactory) {
            return NULL;
        }
        m_shared_ClassFactory->init();
    }
    return m_shared_ClassFactory;
}

YHClassFactory::YHClassFactory(){
    
}

YHClassFactory::~ YHClassFactory(){
    delete m_shared_ClassFactory;
}

void YHClassFactory::init(){
    RegisterBaseClass(int);
    RegisterBaseClass(string);
    RegisterBaseClass(float);
    RegisterBaseClass(double);
    RegisterBaseClass(char);
    
}


void* YHClassFactory::getClasstByName(string className){
    void* pRet = NULL;
    map<string, YHClassObject>::iterator it = m_mapStringClassObjects.find(className);
    if (it != m_mapStringClassObjects.end()) {
        pRet = (it->second.m_classSelector)();
    }
    return pRet;
}


void YHClassFactory::registerClass(string name, CLASS_SELECTOR classSelector, DELETE_CLASS_SELECTOR deleteClassSelector, SET_CLASS_SELECTOR setClassSelector){
    YHClassObject classObject = YHClassObject(name, classSelector, deleteClassSelector, setClassSelector);
    this->registerClass(classObject);
}

void YHClassFactory::registerClass(char* className, CLASS_SELECTOR classSelector, DELETE_CLASS_SELECTOR deleteClassSelector, SET_CLASS_SELECTOR setClassSelector){
    YHClassObject classObject = YHClassObject(className, classSelector, deleteClassSelector, setClassSelector);
    this->registerClass(classObject);
}

void YHClassFactory::registerClass(YHClassObject classObject){
    m_mapStringClassObjects[classObject.m_className] = classObject;
}

void YHClassFactory::deleteClassByName(string className, void* instance){
    map<string, YHClassObject>::iterator it = m_mapStringClassObjects.find(className);
    if (it != m_mapStringClassObjects.end()) {
        (it->second.m_deleteDlassSelector)(instance);
    }
}
 